package android.FiltrosJava;

public class DitherFilter extends PointFilter {	
	protected final static int[] ditherMagic2x2Matrix = {
	 	 0, 2,
	 	 3, 1
	};
	public void setDitherMagic2x2Matrix(){
		matrix = ditherMagic2x2Matrix;
	}
	
	protected final static int[] ditherMagic4x4Matrix = {
	 	 0, 14,  3, 13,
		11,  5,  8,  6,
		12,  2, 15,  1,
		 7,  9,  4, 10
	};
	public void setDitherMagic4x4Matrix(){
		matrix = ditherMagic4x4Matrix;
	}
	
	public final static int[] ditherLines4x4Matrix = {
	 	 0,  1,  2,  3,
		 4,  5,  6,  7,
		 8,  9, 10, 11,
		12, 13, 14, 15
	};
	public void setDitherLines4x4Matrix(){
		matrix = ditherLines4x4Matrix;
	}
	
	public final static int[] dither90Halftone6x6Matrix = {
	 	29, 18, 12, 19, 30, 34,
		17,  7,  4,  8, 20, 28,
		11,  3,  0,  1,  9, 27,
		16,  6,  2,  5, 13, 26,
		25, 15, 10, 14, 21, 31,
		33, 25, 24, 23, 33, 36
	};
	public void setDither90Halftone6x6Matrix(){
		matrix = dither90Halftone6x6Matrix;
	}

	public final static int[] ditherOrdered6x6Matrix = {
		 1, 59, 15, 55,  2, 56, 12, 52,
		33, 17, 47, 31, 34, 18, 44, 28,
		 9, 49,  5, 63, 10, 50,  6, 60,
		41, 25, 37, 21, 42, 26, 38, 22,
		 3, 57, 13, 53,  0, 58, 14, 54,
		35, 19, 45, 29, 32, 16, 46, 30,
		11, 51,  7, 61,  8, 48,  4, 62,
		43, 27, 39, 23, 40, 24, 36, 20 
	};
	public void setDitherOrdered6x6Matrix(){
		matrix = ditherOrdered6x6Matrix;
	}
	
	public final static int[] ditherCluster3Matrix = {
		 9,11,10, 8, 6, 7,
		12,17,16, 5, 0, 1,
		13,14,15, 4, 3, 2,
		 8, 6, 7, 9,11,10,
		 5, 0, 1,12,17,16,
		 4, 3, 2,13,14,15 };
	public void setDitherCluster3Matrix(){
		matrix = ditherCluster3Matrix;
	}
	
	public final static int[] ditherCluster4Matrix = {
		18,20,19,16,13,11,12,15,
		27,28,29,22, 4, 3, 2, 9,
		26,31,30,21, 5, 0, 1,10,
		23,25,24,17, 8, 6, 7,14,
		13,11,12,15,18,20,19,16,
		 4, 3, 2, 9,27,28,29,22,
		 5, 0, 1,10,26,31,30,21,
		 8, 6, 7,14,23,25,24,17 };
	public void setDitherCluster4Matrix(){
		matrix = ditherCluster4Matrix;
	}

	private int[] matrix;
	private int rows, cols, levels;
	private int[] mod;
	private int[] div;
	private int[] map;
	private boolean colorDither;
	private boolean initialized = false;

	public DitherFilter() {
		matrix = ditherMagic2x2Matrix;
		levels = 6;
		colorDither = true;
	}
	
	public void setColorDither(boolean useColorDither){
		colorDither = useColorDither;		
	}
	
   protected void initialize() {
		rows = cols = (int)Math.sqrt(matrix.length);
		map = new int[levels];
		for (int i = 0; i < levels; i++) {
			int v = 255 * i / (levels-1);
			map[i] = v;
		}
		div = new int[256];
		mod = new int[256];
		int rc = (rows*cols+1);
		for (int i = 0; i < 256; i++) {
			div[i] = (levels-1)*i / 256;
			mod[i] = i*rc/256;
		}
	}

	public int[] computeFilter(int px, int py, int[] imageData) {
		if (!initialized) {
			initialized = true;
			initialize();			
		}		
		int r = imageData[0];
		int g = imageData[1];
		int b = imageData[2];
		
		int col = px % cols;
		int row = py % rows;
		int v = matrix[row*cols+col];
		if (colorDither) {
			r = map[mod[r] > v ? div[r] + 1 : div[r]];
			g = map[mod[g] > v ? div[g] + 1 : div[g]];
			b = map[mod[b] > v ? div[b] + 1 : div[b]];
		} else {
			int value = (r+g+b)/3;
			r = g = b = map[mod[value] > v ? div[value] + 1 : div[value]];
		}
		imageData[0] = r;
		imageData[1] = g;
		imageData[2] = b;		
		return imageData;
	}

	@Override
	public int[] applyFilter(int[] pixels) {
		// TODO Auto-generated method stub
		return null;
	}
}